---
title: "Git Commit Signing With GPG"
date: 2020-07-26T20:08:14-05:00
draft: true
tags:
  - git
  - gpg
  - privacy
  - vcs
  - howto
---

You can sign the changes you make to your repositories. This is done to verify that these changes come from a trusted source originally your signature. Repository services often mark these changes as verified or unverified.

In order to sign your commits you need a digital signature. You can create this signature using the [GNU Privacy Guard](https://gnupg.org/).

## Check installation

To check if you have GPG installed, open a terminal in unix-like systems or the `cmd.exe` if you run windows and type:
```bash
$ gpg --version
```

If you don't have it installed (it says command not found or something similar), download it from the [official download site](https://www.gnupg.org/download/) or use your unix distribution [package manager](https://en.wikipedia.org/wiki/Package_manager).

## Common key algoritms

These are the most common key algoritms:

* RSA
* ElGamal
* DSA
* ECDH
* ECDSA
* EdDSA

## Check for existing GPG keys

Type this in the terminal to get the available GPG keys:
```bash
$ gpg --list-secret-keys --keyid-format LONG
```

> If you have gpg version 2 or greater you may write `gpg2 --list-secret-keys --keyid-format LONG` on some systems. If this is the case, configure git to use that version instead with `git config --global gpg.program gpg2`.

After executing that command you should see the keys printed. If you don't want to use them to sign your commits or there are no keys available [generate a new GPG key](#generate-a-new-gpg-key). If you want to use the available keys to sign your commits then [add a key to your Git service account](#add-a-key-to-a-git-service).

## Generate a new GPG key

To generate a new gpg key, type the following commands on your terminal.

For gpg version 2.1.17 or greater:
```bash
$ gpg --full-generate-key
```

You will be propmted to choose the kind of key you want, the key size and the expiration time (leave it empty if you don't want it to expire and press enter).

If you have gpg lesser than 2.1.17 the previous command doesn't work, so type this instead:
```bash
$ gpg --default-new-key-algo rsa4096 --gen-key
```

This will generate specifically an RSA key with key size 4096.

You will also be prompted to enter an email address. You must provide the same email address you use for your web git service. Be sure this email doesn't reply so the service keeps this email address private.

Finally the command will prompt you to type a secure passphrase.

You can now check again for existing GPG keys:
```bash
$ gpg --list-secret-keys --keyid-format LONG
```

You should see an output similar to this:
```bash
/home/user/.gnupg/secring.gpg
------------------------------------
sec   4096R/3AA5C34371567BD2 2016-03-10 [expires: 2017-03-10]
uid                          user 
ssb   4096R/42B317FD4BA89E7A 2016-03-10
```

## Configure git to use your GPG signing key

To configure git to use your GPG signing key you must provide the key ID to your git configuration.

Copy the key ID from the `gpg --list-secret-keys --keyid-format LONG` command output.
```bash
/home/user/.gnupg/secring.gpg
------------------------------------
sec   4096R/3AA5C34371567BD2 2016-03-10 [expires: 2017-03-10]
uid                          user 
ssb   4096R/42B317FD4BA89E7A 2016-03-10
```

For this example the key ID is `3AA5C34371567BD2`. Then you must paste it in the git command like this:
```bash
$ git config --global user.signingkey 3AA5C34371567BD2
```

Finally you need to add your GPG key to your shell profile:
```bash
$ test -r ~/.bash_profile && echo 'export GPG_TTY=$(tty)' >> ~/.bash_profile
$ echo 'export GPG_TTY=$(tty)' >> ~/.profile
```

> The previous command tries to add it to `.bash_profile`, if this fails it will add it to `~/.profile`.

If your system runs windows refer to the [Setting up git+ssh+gpg on Windows](https://dev.to/qm3ster/setting-up-gitsshgpg-on-windows-5c85) tutorial.

## Asociate an email with your GPG key

Your GPG key must be asociated with the email you use to access your online git service. This email must match your commiter identity, this allows you to sign commits and tags.

Use the `gpg --list-keys --keyid-format LONG` command once again and copy the key ID you would like to use. To add an email you must use the `--edit-key <GPG key ID>` flag like this:
```bash
$ gpg --edit-key 3AA5C34371567BD2
```

This will show the next prompt:
```bash
$ gpg>
```

You must type and run the command:
```bash
$ gpg> adduid
```

In the following prompt you must type a name, email address and comments depending on your selection. You can choose between the entries with the keys N, C, and E.
```bash
Real Name: SomeUser
  Email address: example_mail@service.com
  Comment: My service key
  Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit?
```

As you can see you must type O to save your selections. After that enter the passphrase that corresponds to your key. Once you finished this you can follow the process of [adding a key to your git service](#add-a-key-to-a-git-service)

## Signing commits and tags

Before you can sign commits and tags you must configure your git client.

For git versions `2.0.0` and above you run:
```bash
$ git config commit.gpgsign true
```

If you want to sign all commits by default in any local repository on your system:
```bash
$ git config --global commit.gpgsign true
```

If you want to avoid typing you passphrase every time you sign a commit or a tag, you can use a key management agent. For MacOS there are the [GPG Tools](https://gpgtools.org/), for windows systems you can use [Gpg4win](https://www.gpg4win.org/), for linux based systems you can use [gpg-agent](http://linux.die.net/man/1/gpg-agent)

If you have multiple keys and you want to use another identity you must [reconfigure git to use your signing key](#configure-git-to-use-your-gpg-signing-key) again.

### Sign a commit

When commiting changes to your local branch, add the `-S` flag to your git command to sign your commit:
```bash
$ git commit -S -m "Your commit message"
```

If you haven't configured your gpg agent you must type the passphrase for your key.

When you are done with your commits, you can push them to your remote repository on your online git service.
```bash
$ git push
```

You can now go to your online service and see that your commits are now marked as verified.

### Sign a tag

To sign a tag you just add the `-s` (notice the lowercase) flag to your `git tag` command.
```bash
$ git tag -s <my-tag>
```

This creates a signed tag. To verify your signed tag  you can pass the `-v` flag to the `git tag` command.
```bash
$ git tag -v <my-tag>
```

## Add a key to a git service

In order to add a key to your git service you need to copy the GPG key ID for the key you wan to use. You can copy this when you [check for existing GPG keys](#check-for-existing-gpg-keys).

For the example key the id is shown first:
```bash
$ gpg --list-secret-keys --keyid-format LONG
/home/user/.gnupg/secring.gpg
------------------------------------
sec   4096R/3AA5C34371567BD2 2016-03-10 [expires: 2017-03-10]
uid                          user 
ssb   4096R/42B317FD4BA89E7A 2016-03-10
```

You can see the key for this example is `3AA5C34371567BD2`. You must use this id in the following command to get the public key block:
```bash
$ gpg --armor --export 3AA5C34371567BD2
```

This will print out your GPG key. This is a block of text that begins with `-----BEGIN PGP PUBLIC KEY BLOCK-----` and ends with `-----END PGP PUBLIC KEY BLOCK-----`.

Copy this block of text to your system clipboard and paste it on your git service's web interface. This may be under the settings page.

## References:

+ [OpenPGP Message Format]: <https://www.ietf.org/rfc/rfc4880.txt>
+ [Migrate GPG keys]: <http://www.koozie.org/blog/2014/07/migrating-gnupg-keys-from-one-computer-to-another/>
